package com.codeoss.module.workflow.service.impl;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.codeoss.framework.service.impl.BaseService;
import com.codeoss.framework.workflow.def.DecisionNodeDef;
import com.codeoss.framework.workflow.def.EndNodeDef;
import com.codeoss.framework.workflow.def.ForkNodeDef;
import com.codeoss.framework.workflow.def.JoinNodeDef;
import com.codeoss.framework.workflow.def.LineDef;
import com.codeoss.framework.workflow.def.NodeDef;
import com.codeoss.framework.workflow.def.ServiceNodeDef;
import com.codeoss.framework.workflow.def.StartNodeDef;
import com.codeoss.framework.workflow.def.TaskNodeDef;
import com.codeoss.framework.workflow.def.WorkflowDef;
import com.codeoss.framework.workflow.parser.IWorkflowElementParser;
import com.codeoss.module.ir.model.IrWorkflow;
import com.codeoss.module.ir.service.IIrWorkflowService;
import com.codeoss.module.workflow.dao.WorkflowWorkflowMapper;
import com.codeoss.module.workflow.model.WorkflowActivity;
import com.codeoss.module.workflow.model.WorkflowTransition;
import com.codeoss.module.workflow.model.WorkflowWorkflow;
import com.codeoss.module.workflow.service.IWorkflowActivityService;
import com.codeoss.module.workflow.service.IWorkflowTransitionService;
import com.codeoss.module.workflow.service.IWorkflowWorkflowService;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;

@Service
public class WorkflowWorkflowService extends BaseService<WorkflowWorkflowMapper, WorkflowWorkflow>
		implements IWorkflowWorkflowService {
	@Autowired
	private IIrWorkflowService irWorkflowService;
	@Autowired
	private IWorkflowActivityService workflowActivityService;
	@Autowired
	private IWorkflowTransitionService workflowTransitionService;
	@Autowired
	@Qualifier("workflowParser")
	private IWorkflowElementParser workflowElementParser;
	@Autowired
	private ObjectMapper objectMapper;
	@Override
	@Transactional
	public void deploy(String code) {
		// TODO Auto-generated method stub
		IrWorkflow irWorkflow=irWorkflowService.getIrWorkflowByCode(code);
		String json=irWorkflow.getJsonContent();
		WorkflowDef workflowDef=null;
		try {
			ObjectNode modelNode=(ObjectNode) objectMapper.readTree(json);
			workflowDef=(WorkflowDef)workflowElementParser.parse(null, modelNode);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			throw new RuntimeException(e);
		}
		
		int workflowVersion;
		QueryWrapper<WorkflowWorkflow> queryWrapper=new QueryWrapper<WorkflowWorkflow>();
		queryWrapper.select("max(workflow_version) as maxseqno").eq("code", code);
		List<Map<String,Object>> mapList=listMaps(queryWrapper);
		if(mapList.size()==0) {
			workflowVersion=1;
		}else if(mapList.get(0)==null) {
			workflowVersion=1;
		}else {
			Object value=mapList.get(0).get("maxseqno");
			if(value instanceof BigDecimal) {
				workflowVersion=((BigDecimal)value).intValue();
			}else {
				workflowVersion =(Integer)value;
			}
			workflowVersion++;
		}
		
		WorkflowWorkflow workflowWorkflow=new WorkflowWorkflow();
		workflowWorkflow.setCode(workflowDef.getCode());
		workflowWorkflow.setName(irWorkflow.getName());
		workflowWorkflow.setDescription(irWorkflow.getDescription());
		workflowWorkflow.setFormCode(irWorkflow.getFormCode());
		workflowWorkflow.setMobileFormCode(irWorkflow.getMobileFormCode());
		workflowWorkflow.setJsonContent(irWorkflow.getJsonContent());
		workflowWorkflow.setWorkflowVersion(workflowVersion);
		insert(workflowWorkflow);
		
		List<NodeDef> nodeDefList=workflowDef.getNodeList();
		for(int i=0;i<nodeDefList.size();i++) {
			NodeDef nodeDef=nodeDefList.get(i);
			String type=nodeDef.getType();
			if("start".equals(type)) {
				createActivity(workflowWorkflow,(StartNodeDef)nodeDef);
			}else if("end".equals(type)) {
				createActivity(workflowWorkflow,(EndNodeDef)nodeDef);
			}else if("task".equals(type)) {
				createActivity(workflowWorkflow,(TaskNodeDef)nodeDef);
			}else if("service".equals(type)) {
				createActivity(workflowWorkflow,(ServiceNodeDef)nodeDef);
			}else if("decision".equals(type)) {
				createActivity(workflowWorkflow,(DecisionNodeDef)nodeDef);
			}else if("fork".equals(type)) {
				createActivity(workflowWorkflow,(ForkNodeDef)nodeDef);
			}else if("join".equals(type)) {
				createActivity(workflowWorkflow,(JoinNodeDef)nodeDef);
			}
		}
		
		List<LineDef> lineDefList=workflowDef.getLineList();
		for(int i=0;i<lineDefList.size();i++) {
			LineDef lineDef=lineDefList.get(i);
			NodeDef fromNode=workflowDef.getNodeDefById(lineDef.getFromNodeId());
			NodeDef toNode=workflowDef.getNodeDefById(lineDef.getToNodeId());
			
			WorkflowTransition workflowTransition=new WorkflowTransition();
			workflowTransition.setWorkflowWorkflowId(workflowWorkflow.getId());
			workflowTransition.setFromActivityId((Long)fromNode.getAttribute("id"));
			workflowTransition.setToActivityId((Long)toNode.getAttribute("id"));
			workflowTransition.setFromNodeId(lineDef.getFromNodeId());
			workflowTransition.setToNodeId(lineDef.getToNodeId());
			workflowTransition.setName(lineDef.getName());
			workflowTransitionService.insert(workflowTransition);
		}
	}

	protected void createActivity(WorkflowWorkflow workflowWorkflow,StartNodeDef startNode) {
		WorkflowActivity workflowActivity=new WorkflowActivity();
		workflowActivity.setName("开始");
		workflowActivity.setStartActivity(true);
		workflowActivity.setEndActivity(false);
		workflowActivity.setActivityType("start");
		workflowActivity.setWorkflowWorkflowId(workflowWorkflow.getId());
		workflowActivity.setNodeId(startNode.getId());
		workflowActivityService.insert(workflowActivity);
		startNode.setAttribute("id", workflowActivity.getId());
	}
	
	protected void createActivity(WorkflowWorkflow workflowWorkflow,EndNodeDef endNode) {
		WorkflowActivity workflowActivity=new WorkflowActivity();
		workflowActivity.setName("结束");
		workflowActivity.setStartActivity(false);
		workflowActivity.setEndActivity(true);
		workflowActivity.setActivityType("end");
		workflowActivity.setWorkflowWorkflowId(workflowWorkflow.getId());
		workflowActivity.setNodeId(endNode.getId());
		workflowActivityService.insert(workflowActivity);
		endNode.setAttribute("id", workflowActivity.getId());
	}
	
	protected void createActivity(WorkflowWorkflow workflowWorkflow,TaskNodeDef taskNode) {
		WorkflowActivity workflowActivity=new WorkflowActivity();
		workflowActivity.setName(taskNode.getName());
		workflowActivity.setStartActivity(false);
		workflowActivity.setEndActivity(false);
		workflowActivity.setActivityType("task");
		workflowActivity.setWorkflowWorkflowId(workflowWorkflow.getId());
		workflowActivity.setNodeId(taskNode.getId());
		workflowActivityService.insert(workflowActivity);
		taskNode.setAttribute("id", workflowActivity.getId());
	}
	
	protected void createActivity(WorkflowWorkflow workflowWorkflow,ServiceNodeDef serviceNode) {
		WorkflowActivity workflowActivity=new WorkflowActivity();
		workflowActivity.setName(serviceNode.getName());
		workflowActivity.setStartActivity(false);
		workflowActivity.setEndActivity(false);
		workflowActivity.setActivityType("service");
		workflowActivity.setWorkflowWorkflowId(workflowWorkflow.getId());
		workflowActivity.setNodeId(serviceNode.getId());
		workflowActivityService.insert(workflowActivity);
		serviceNode.setAttribute("id", workflowActivity.getId());
	}

	protected void createActivity(WorkflowWorkflow workflowWorkflow,DecisionNodeDef decisionNode) {
		WorkflowActivity workflowActivity=new WorkflowActivity();
		workflowActivity.setName("决策节点");
		workflowActivity.setStartActivity(false);
		workflowActivity.setEndActivity(false);
		workflowActivity.setActivityType("decision");
		workflowActivity.setWorkflowWorkflowId(workflowWorkflow.getId());
		workflowActivity.setNodeId(decisionNode.getId());
		workflowActivityService.insert(workflowActivity);
		decisionNode.setAttribute("id", workflowActivity.getId());
	}
	
	protected void createActivity(WorkflowWorkflow workflowWorkflow,ForkNodeDef forkNode) {
		WorkflowActivity workflowActivity=new WorkflowActivity();
		workflowActivity.setName("分支节点");
		workflowActivity.setStartActivity(false);
		workflowActivity.setEndActivity(false);
		workflowActivity.setActivityType("fork");
		workflowActivity.setWorkflowWorkflowId(workflowWorkflow.getId());
		workflowActivity.setNodeId(forkNode.getId());
		workflowActivityService.insert(workflowActivity);
		forkNode.setAttribute("id", workflowActivity.getId());
	}
	
	protected void createActivity(WorkflowWorkflow workflowWorkflow,JoinNodeDef joinNode) {
		WorkflowActivity workflowActivity=new WorkflowActivity();
		workflowActivity.setName("合并节点");
		workflowActivity.setStartActivity(false);
		workflowActivity.setEndActivity(false);
		workflowActivity.setActivityType("join");
		workflowActivity.setWorkflowWorkflowId(workflowWorkflow.getId());
		workflowActivity.setNodeId(joinNode.getId());
		workflowActivityService.insert(workflowActivity);
		joinNode.setAttribute("id", workflowActivity.getId());
	}
	
	@Override
	public WorkflowWorkflow getMaxVersionWorkflowWorkflowByCode(String code) {
		// TODO Auto-generated method stub
		QueryWrapper<WorkflowWorkflow> query=new QueryWrapper<WorkflowWorkflow>();
		query.eq("code", code);
		
		int workflowVersion;
		QueryWrapper<WorkflowWorkflow> queryWrapper=new QueryWrapper<WorkflowWorkflow>();
		queryWrapper.select("max(workflow_version) as maxseqno").eq("code", code);
		List<Map<String,Object>> mapList=listMaps(queryWrapper);
		if(mapList.size()==0) {
			workflowVersion=0;
		}else if(mapList.get(0)==null) {
			workflowVersion=0;
		}else {
			workflowVersion =(Integer)mapList.get(0).get("maxseqno");
		}
		if(workflowVersion!=0) {
			query.eq("workflow_version", workflowVersion);
		}
		return getOne(query);
	}
}